package com.star.uc.biz;

import com.star.common.core.context.ThreadContext;
import com.star.common.core.contract.constant.ContextConstants;
import com.star.common.kit.language.chain.LanguageChainFilterFactory;
import com.star.message.api.contract.command.SendEmailCommand;
import com.star.message.api.service.MessageEmailApi;
import com.star.uc.contract.dto.request.EmailSendRequest;
import com.star.uc.contract.dto.request.MonitorRequest;
import com.star.uc.contract.enums.LimitTypeEnum;
import com.star.uc.contract.enums.UserGeneratorCodeTypeEnum;
import com.star.uc.contract.enums.monitor.EmailCaptchaMonitorEnum;
import com.star.uc.contract.exception.LimitRateException;
import com.star.uc.infras.utils.GenerateCodeUtils;
import com.star.uc.infras.utils.LimitFilterUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * email业务处理类
 *
 * @author zhouhengzhe
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EmailBizService {

    private final LanguageChainFilterFactory languageChainFilterFactory;

    private final LimitFilterUtils limitFilterUtils;

    private final GenerateCodeUtils generateCodeUtils;

    private final MessageEmailApi messageEmailApi;

    /**
     * 发生邮件
     *
     * @param emailSendRequest 邮件发送请求
     */
    public void sendEmail(EmailSendRequest emailSendRequest) {
        //获取语言编码
        String languageCode = languageChainFilterFactory.handle(emailSendRequest.getLanguageCode());
        try {
            //ip限流（同一个应用同一个IP只能注册10个，防止人家用ip刷账号，虽然他有代理，但是我们就是要恶心他）
            limitFilterUtils.limitIp(emailSendRequest.getEmail(),
                    emailSendRequest.getTenantId(), emailSendRequest.getClientType(), LimitTypeEnum.EMAIL.getCode());

            //同一个应用同一个邮箱限流(分，时，天)，简单理解为就是一个邮箱在某段时间内只能发送几个邮件
            limitFilterUtils.limitSendEmailOrSmsOrIpCount(emailSendRequest.getEmail(),
                    emailSendRequest.getTenantId(), LimitTypeEnum.EMAIL.getCode(), emailSendRequest.getClientType());

            //同一个应用同一个IP限流(分，时，天)，简单理解为就是一个IP在某段时间内只能发送几个邮件
            limitFilterUtils.limitSendEmailOrSmsOrIpCount(ThreadContext.get(ContextConstants.IP),
                    emailSendRequest.getTenantId(), LimitTypeEnum.IP.getCode(), emailSendRequest.getClientType());
        } catch (LimitRateException e) {
            //监控，默认不处理
            EmailCaptchaMonitorEnum emailCaptchaMonitorEnum = EmailCaptchaMonitorEnum.getByCode();
            emailCaptchaMonitorEnum.monitor(MonitorRequest
                    .builder()
                    .tenantId(emailSendRequest.getTenantId())
                    .sendType(emailSendRequest.getSendType())
                    .languageCode(languageCode)
                    .value(emailSendRequest.getEmail())
                    .flag(Boolean.FALSE)
                    .reason("rate-limit")
                    .build());
            throw e;
        }
        //生成验证码
        String code = generateCodeUtils.generateCode(UserGeneratorCodeTypeEnum.EMAIL.getCode(),
                emailSendRequest.getSendType(), emailSendRequest.getTenantId(), emailSendRequest.getEmail());
        messageEmailApi.sendEmail(SendEmailCommand
                .builder()
                .tenantId(emailSendRequest.getTenantId())
                .email(emailSendRequest.getEmail())
                .languageCode(languageCode)
                .code(code)
                .build());
        //监控，默认不处理
        EmailCaptchaMonitorEnum emailCaptchaMonitorEnum = EmailCaptchaMonitorEnum.getByCode();
        emailCaptchaMonitorEnum.monitor(MonitorRequest
                .builder()
                .tenantId(emailSendRequest.getTenantId())
                .sendType(emailSendRequest.getSendType())
                .languageCode(languageCode)
                .value(emailSendRequest.getEmail())
                .flag(Boolean.TRUE)
                .reason("commit")
                .build());
    }


}
